from flask import Flask, request, jsonify, send_from_directory
from flask_cors import CORS
import mysql.connector
import jwt
from datetime import datetime, timedelta
from functools import wraps
from config import DB_CONFIG, JWT_SECRET_KEY, JWT_ALGORITHM, JWT_EXPIRATION_DELTA
from passlib.hash import pbkdf2_sha256
import os
import urllib.parse

# 获取当前文件所在目录的绝对路径
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_DIR = os.path.join(BASE_DIR, 'static')

app = Flask(__name__, 
            static_folder=STATIC_DIR,
            static_url_path='/static')  # 修改这里，添加static_url_path
CORS(app)  # 解决跨域问题
app.config['SECRET_KEY'] = JWT_SECRET_KEY

# 数据库连接函数
def get_db_connection():
    try:
        return mysql.connector.connect(**DB_CONFIG)
    except mysql.connector.Error as err:
        print(f"Database connection error: {err}")
        return None


# 生成 JWT 令牌
def generate_token(username):
    payload = {
        'user': username,
        'exp': datetime.utcnow() + timedelta(minutes=JWT_EXPIRATION_DELTA)
    }
    token = jwt.encode(payload, app.config['SECRET_KEY'], algorithm=JWT_ALGORITHM)
    return token


# 验证 JWT 令牌
def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = request.headers.get('Authorization')
        if not token:
            return jsonify({'message': 'Token is missing!'}), 401
        try:
            token = token.replace('Bearer ', '')
            data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
        except jwt.ExpiredSignatureError:
            return jsonify({'message': 'Token has expired!'}), 401
        except jwt.InvalidTokenError:
            return jsonify({'message': 'Invalid token!'}), 401
        return f(*args, **kwargs)

    return decorated


# 用户注册
@app.route('/register', methods=['POST'])
def register():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not username or not password:
        return jsonify({'message': 'Username and password are required!'}), 400
    hashed_password = pbkdf2_sha256.hash(password)
    db = get_db_connection()
    if db:
        try:
            cursor = db.cursor()
            cursor.execute("SELECT * FROM 用户表 WHERE 用户名 = %s", (username,))
            user = cursor.fetchone()
            if user:
                return jsonify({'message': 'Username already exists!'}), 400
            cursor.execute("INSERT INTO 用户表 (用户名, 密码) VALUES (%s, %s)", (username, hashed_password))
            db.commit()
            return jsonify({'message': 'User registered successfully!'}), 201
        except mysql.connector.Error as err:
            print(f"Database error: {err}")
            return jsonify({'message': 'Database error!'}), 500
        finally:
            db.close()
    return jsonify({'message': 'Database connection error!'}), 500


# 用户登录
@app.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    if not username or not password:
        return jsonify({'message': 'Username and password are required!'}), 400
    db = get_db_connection()
    if db:
        try:
            cursor = db.cursor()
            cursor.execute("SELECT 密码 FROM 用户表 WHERE 用户名 = %s", (username,))
            user = cursor.fetchone()
            if user and pbkdf2_sha256.verify(password, user[0]):
                token = generate_token(username)
                return jsonify({'token': token}), 200
            return jsonify({'message': 'Invalid username or password!'}), 401
        except mysql.connector.Error as err:
            print(f"Database error: {err}")
            return jsonify({'message': 'Database error!'}), 500
        finally:
            db.close()
    return jsonify({'message': 'Database connection error!'}), 500


# 受保护的 API
@app.route('/protected', methods=['GET'])
@token_required
def protected():
    return jsonify({'message': 'This is a protected route!'}), 200


# 提供静态文件服务
@app.route('/')
def index():
    return send_from_directory(os.path.join(STATIC_DIR, 'html'), 'index.html')

# 处理HTML文件
@app.route('/<path:filename>')
def serve_static(filename):
    try:
        # 解码URL编码的文件名
        decoded_filename = urllib.parse.unquote(filename)
        
        # 根据文件扩展名确定目录
        if filename.endswith('.html'):
            return send_from_directory(os.path.join(STATIC_DIR, 'html'), decoded_filename)
        elif filename.endswith('.css'):
            return send_from_directory(os.path.join(STATIC_DIR, 'css'), decoded_filename)
        elif filename.endswith(('.jpg', '.jpeg', '.png', '.gif')):
            return send_from_directory(os.path.join(STATIC_DIR, 'img'), decoded_filename)
        elif filename.endswith('.js'):
            return send_from_directory(os.path.join(STATIC_DIR, 'js'), decoded_filename)
        else:
            return "File type not supported", 404
    except Exception as e:
        print(f"Error serving static file: {e}")
        return "File not found", 404

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5001, debug=True) 